import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.text.Normalizer;
import java.util.ArrayList;
import java.io.FileWriter;

import mac_tools.MacCharCode;



/**
 * winchkg.jar のランチャー
 * 
 * winchkg.jarと同じフォルダにおかれて、winchkg-new.jarがあれば、winchkg.jar => winchkg-old.jarにリネーム
 * winckg-new.jar=>winckg.jarにリネームする
 * 
 * winchkg.jar を システムメモリを調べて、できるだけ大きいメモリを割り当てて起動する。
 * @author ikechan
 *
 */
public class winchkglnch {
	private static final String MyProgname = "winchkglnch";
	private static final String Version = "1.1.6";
	private static final String MyName = MyProgname + " " + Version ;
	private static final String NewFileName = "winchkg-new.jar";
	private static final String CurFileName = "winchkg.jar";
	private static final String OldFileName = "winchkg-back.jar";
	private static final String IniFileName = "winchkglnch.ini";
	private static final String LogFileName = "winchkglnch.log";
	private logMessage LogFile=null;
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		if(args.length>=1){
			if(0==args[0].compareToIgnoreCase("-version")){
				System.out.println(MyName);
				return ;
			}
		}
		//FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
		//System.setOut(new PrintStream(new BufferedOutputStream(fdOut, 128), true));
		new winchkglnch(args);
		
	}
	
	
	winchkglnch(String[] args){
		
		MyDirectory my = new MyDirectory();
		File mydir = my.getDirectory();
		String myPath = mydir.getAbsolutePath();
		
		String inifile = myPath + File.separator + IniFileName;
		File file = new File(inifile);
		FileWriter fw;
		try {
			fw = new  FileWriter(file);
			fw.write("version = " + Version);
			fw.close();
		} catch (IOException e1) {
		//	e1.printStackTrace();
		}

		LogFile = new logMessage(myPath);
		
		String newFileName = NewFileName;
		String curFileName = CurFileName;
		String oldFileName = OldFileName;
		
		LogFile.println("Mypath   = " + myPath);
		LogFile.println("NewFile  = " + newFileName);
		LogFile.println("CurFile  = " + curFileName);
		LogFile.println("OldFile  = " + oldFileName);
		String wcgcur = updateFile(myPath, newFileName, curFileName,
				oldFileName);
		LogFile.println("Winchkg  = " + wcgcur);
		
		
		// winchkgに必要なメモリを割り当てて起動
		String xms = null;
		String xmx = null;
		ArrayList<String> lst = new ArrayList<String>();
		for(int i=0;i<args.length;i++){
			String s = args[i];
			s = s.trim();
			String s2 = s.toLowerCase();
			
			LogFile.println("Argument " + i + " " + s2 );

			
			if(s2.length()>4){
				String t = s2.substring(0,3);
				if(t.compareTo("-xms")==0){
					xms = s2.substring(4,s.length()-1);
					continue;
				}
				else if(t.compareTo("-xmx")==0){
					xmx = s2.substring(4,s.length()-1);
					continue;
				}
				
			}
			lst.add(new String(s));
		}
		
		if(xms==null || xmx==null){
			//long totalmem = SystemMemoryManager.getTotalMemory();
			long defmem = SystemMemoryManager.getDefaultMemory();
			LogFile.println("Get memory =" + defmem + "M");
			defmem /= 10;
			defmem *= 8;
			if(defmem<256){
				defmem = 256;
			}
			xms = String.format("-Xms%dM", defmem);
			xmx = String.format("-Xmx%dM", defmem);
		}
		int addcmd = lst.size();
		String[] cmd = new String[5+addcmd];
		cmd[0] = "java";
		cmd[1] = xms;
		cmd[2] = xmx;
		cmd[3] = "-jar";
		
		// mac の日本語ディレクトリ対策
		// カレントディレクトリをとると、SJISで取得される）
		String curjar = null;
		if(MyDirectory.getOsName()==MyDirectory.OSName.MAC_OSX){
			// 結局macで”レコーダー”がうまく変換できないので、macの場合は絶対パスでは指定しないことにする
			curjar = CurFileName;
		}
		else{
			curjar = new String(wcgcur);
		}
		cmd[4] = curjar;
		// ここまで
		
		for(int i=0;i<addcmd;i++){
			cmd[5+i]=lst.get(i);
		}

		LogFile.println("Invoking...");
		for(int i=0;i<cmd.length;i++){
			LogFile.print(" "+cmd[i]);
		}
		LogFile.println(" ");
		LogFile.flush();
		
		ProcessBuilder pb = new ProcessBuilder(cmd);
		try {
			Process p = pb.start();
//			int ret = p.waitFor();
//			if(ret == 0){
//				LogFile.println(" Success");
//			}
//			else{
//				LogFile.println(" Fail : return code = " + ret);
//			}
		} catch (IOException e) {
			LogFile.println(e.getMessage());
			e.printStackTrace();
		}
//		} catch (InterruptedException e) {
//			LogFile.println(e.getMessage());
//			e.printStackTrace();
//		}
		LogFile.close();
	
	}
	private void dumpByte(byte[] b){
		for(int i=0;i<b.length;i++){
			String s = String.format("%02x ", b[i]);
			if(i%16 == 15) s += "\n";
			LogFile.print(s);
		}
		LogFile.println("-------------------------------------");
		
	}
	private void dumpString(String str){
		byte[] b = str.getBytes();
		dumpByte(b);
	}
	class logMessage{
		private FileWriter fileWriter=null;
		private BufferedWriter bufferedWriter = null;
		public logMessage(String mypath){
			try {
				fileWriter = new  FileWriter(mypath + File.separator + LogFileName);
				bufferedWriter = new BufferedWriter(fileWriter);
			} catch (IOException e1) {
				
			}
		}
		public void close(){
			if(bufferedWriter!=null){
				try {
					bufferedWriter.close();
					fileWriter.close();
				} catch (IOException e) {
				}
			}
		}
		public void flush(){
			if(bufferedWriter!=null){
				try {
					bufferedWriter.flush();
					fileWriter.flush();
				} catch (IOException e) {
				}
			}
		}
		public void print(String mes){
			System.out.print(mes);
			if(bufferedWriter!=null){
				try {
					bufferedWriter.write(mes);
				} catch (IOException e) {
				}
			}
		}
		public void println(String mes){
			print(mes);
			System.out.println(" ");
			if(bufferedWriter!=null){
				try {
					bufferedWriter.newLine();
				} catch (IOException e) {
				}
			}
		}
	}
	
	private String updateFile(String myPath, String newFileName,
			String curFileName, String oldFileName) {
		String wcgnew = myPath + File.separator + newFileName;
		String wcgcur = myPath +  File.separator + curFileName;
		String wcgold = myPath  + File.separator + oldFileName;
		
		File newfile = new File(wcgnew);
		
		LogFile.println("\n*** *** *** *** *** ***");
		LogFile.println(MyName);
		LogFile.println("Path = "+ myPath  + File.separator);
		
		if(newfile.isFile()){			// 新しいファイルがあれば
			LogFile.println("New winchkg detected.");
			LogFile.println("Updating...");
			File backfile = new File(wcgold);	// backファイルがあれば削除
			if(backfile.isFile()){
				LogFile.println("Deleting : " + backfile);
				if(backfile.delete()){
					LogFile.println(" Success");
				}
			}
			File curfile = new File(wcgcur);	// 現行をbackファイルにリネーム
			File destfile = new File(wcgold);	
			LogFile.println("Backuping : " + wcgcur + " to " + wcgold );
			int retrycount=0;
			for(;retrycount<10;retrycount++){
				if(curfile.renameTo(destfile)){
					LogFile.println(" Success");
					break;
				}
				LogFile.println(" Retry to rename. " );
				try{
					Thread.sleep(1000); //1秒Sleepする
		        }catch(InterruptedException e){}
			}
			if(retrycount<10){
				LogFile.println("Renaming : " + wcgnew + " to " + wcgcur );
				File newdest = new File(wcgcur);   // 新ファイルを現行ファイルにリネーム
				if(newfile.renameTo(newdest)){
					LogFile.println(" Success " );
				}
				else{
					LogFile.println(" Fail " );
				}
			}
			else{
				LogFile.println(" Fail (time out) " );
			}
		}
		return wcgcur;
	}

}
